﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using Kooboo.Collections;
using Kooboo.Commerce.AddIn;
using Kooboo.Commerce.Contexts.Customers;
using Kooboo.Commerce.Contexts.Payments;
using Kooboo.Domain;
using Kooboo.IoC;


namespace Kooboo.Commerce
{
    public partial class ServiceHost : IVistor, IEditor
    {
        //public IPayment LocatePayment(IOrder order)
        //{
        //    return this.QueryPayments()
        //        .Where(i => i.MethodName == order.PaymentName)
        //        .FirstOrDefault();
        //}

        //public IPayment LocatePayment(ICart cart)
        //{
        //    return this.QueryPayments()
        //        .Where(i => i.MethodName == cart.PaymentName)
        //        .FirstOrDefault();
        //}

        public void SyncPayments()
        {
            var payments = this.QueryPayments().Select(i=>new
            {
                i.MethodName,
                i.HeadLine,
                i.IsRedirect
            });


            var addins = ObjectContainer.CreateInstances<IPaymentMethod>()
                .Select(i=>new
                {
                    MethodName = i.Name,
                    i.HeadLine,
                    IsRedirect = !(i is IDirectPaymentMethod)
                });


            var result = payments.Compare(addins, (i1, i2) => i1.MethodName == i2.MethodName, (i1, i2) =>
                {
                    if (i1.IsRedirect != i2.IsRedirect)
                    {
                        var payment = this.QueryPayments()
                            .Where(i => i.MethodName == i1.MethodName)
                            .FirstOrDefault();

                        payment.IsRedirect = i2.IsRedirect;

                        this.Put(payment);
                    }
                });

            foreach (var i in result.Added)
            {
                var payment = ObjectContainer.CreateInstance<IPayment>();
                payment.MethodName = i.MethodName;
                payment.HeadLine = i.HeadLine;
                payment.IsRedirect = i.IsRedirect;
                payment.PercentChange = 0;
                payment.AmountChange = 0;
                payment.IsEnable = false;

                this.Post(payment);
            }

            foreach (var i in result.Deleted)
            {
                var payment = ObjectContainer.CreateInstance<IPayment>();
                payment.MethodName = i.MethodName;

                this.Delete(payment);
            }
                
        }

   

        #region Customer
        public void Post(ICustomer customer, string password)
        {

            using (var transaction = ObjectContainer.CreateInstance<TransactionContext>())
            {
                try
                {

                    if (string.IsNullOrWhiteSpace(customer.UserName))
                    {
                        throw new ArgumentNullException("Customer.UserName");
                    }

                 
                    if (this.QueryCustomers().Any(i => i.UserName == customer.UserName))
                    {
                        throw new DuplicateNameException(customer.UserName);
                    }

                    var find = Kooboo.Connect.UserServices.FindUser(customer.UserName);
                    if (find == null)
                    {

                        var status = Kooboo.Connect.UserServices.CreateUser(customer.UserName, password, customer.MailAddress);

                        if (status != Connect.UserCreateStatus.Success)
                        {
                            throw new InvalidOperationException(status.ToString());
                        }

                    }
                    customer.CreateDate = DateTime.Now;

                    var repository = ContextContainer.Current.Resolve<ICustomerRepository>();

                    repository.Post(customer);

                    transaction.Commit();
                }
                catch
                {
                    transaction.Rollback();
                    throw;
                }
            }

        }

        public void Put(ICustomer customer)
        {
            using (var transaction = ObjectContainer.CreateInstance<TransactionContext>())
            {
                try
                {
                    if (string.IsNullOrWhiteSpace(customer.UserName))
                    {
                        throw new ArgumentNullException("Customer.UserName");
                    }

                    if (this.QueryCustomers().Any(i => i.UserName == customer.UserName && i.Id != customer.Id))
                    {
                        throw new DuplicateNameException(customer.UserName);
                    }

                    var user = Kooboo.Connect.UserServices.FindUser(customer.UserName);
                    if (user == null)
                    {
                        throw new KeyNotFoundException(customer.UserName);
                    }


                    var find = this.QueryCustomers()
                        .Where(i => i.Id == customer.Id)
                        .FirstOrDefault();

                    find.Birthday = customer.Birthday;
                    find.City = customer.City;
                    find.Country = customer.Country;
                    find.FirstName = customer.FirstName;
                    find.Gender = customer.Gender;
                    find.LastName = customer.LastName;
                    find.MailAddress = customer.MailAddress;
                    find.MiddleName = customer.MiddleName;
                    find.Mobile = customer.Mobile;
                    find.SavingPoint = customer.SavingPoint;
                    find.StarLevel = customer.StarLevel;
                    find.Telphone = customer.Telphone;
                    find.UserName = customer.UserName;

                    var repository = ContextContainer.Current.Resolve<ICustomerRepository>();
                    repository.Put(find);

                    transaction.Commit();
                }
                catch
                {
                    transaction.Rollback();
                    throw;
                }
            }

        }

        public void Delete(ICustomer customer)
        {

            using (var transaction = ObjectContainer.CreateInstance<TransactionContext>())
            {
                try
                {
                    var repository = ContextContainer.Current.Resolve<ICustomerRepository>();
                    repository.Delete(customer);

                    transaction.Commit();
                }
                catch
                {
                    transaction.Rollback();
                    throw;
                }
            }

        }

        #endregion

    }
}
